package com.sdtv.basemodule.rx;

import android.text.TextUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.sdtv.basemodule.bean.BaseResult;
import com.sdtv.basemodule.bean.Results;
import com.sdtv.basemodule.bean.SqlEntityBean;
import com.sdtv.basemodule.cache.DaoUtils;
import com.sdtv.basemodule.utils.EmptyUtils;

import java.util.List;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

/**
 * @ProjectName: MediunFusion
 * @Package: com.sdtv.basemodule.rx
 * @ClassName: BaseObserver
 * @Description: 处理返回数据的公共类
 * --公共的业务逻辑在这里面处理--
 * @Author: 小郭同学
 * @CreateDate: 2019-06-25 17:37
 * @UpdateRemark: 更新说明
 * @Version: 1.0
 */
public abstract class BaseObserver<T> implements Observer<java.lang.String> {

    private Class<T> clazz;
    // 缓存数据的KEY  --如果不使用缓存  该KEY为空
    private String userKey = "";


    public BaseObserver() {
    }

    /**
     * 构造器
     *
     * @param cla
     */
    public BaseObserver(Class cla) {
        this.clazz = cla;
    }

    /**
     * 如果有数据要缓存 可以使用该构造方法
     *
     * @param cla class对象 用来解析JSON
     * @param key 缓存使用的key
     */
    public BaseObserver(Class cla, String key) {
        this.clazz = cla;
        this.userKey = key;
    }

    @Override
    public void onSubscribe(Disposable d) {

    }

    /**
     * 解析数据的核心方法，缓存也在该方法里面处理
     * 该方法里面调用doNext()方法，
     * 在页面中实现doNext(T t)方法处理页面逻辑信息
     * 数据格式各不相同，在实际使用中可以自定义observer来重写onNext()方法来处理数据
     *
     * @param response
     */
    @Override
    public void onNext(java.lang.String response) {
        LogUtils.e("response :" + response);
        if (EmptyUtils.isEmpty(response)) {
            onEmpty();
            return;
        }
        try {
            BaseResult baseResult = new Gson().fromJson(response, BaseResult.class);
            if (null != baseResult && 200 == baseResult.getCode()) {
                Results<T> results = baseResult.getResults();
                if (results.getRet() == 405 || results.getRet() == 403) {
                    //提示用户被登出--
                    showErrorTost(results.getRet(), results.getMsg());
                    return;
                }
                if (results.getRet() != 200) {
                    LogUtils.e("请求数据失败，弹出失败信息 " + results.getRet());
//                    LogUtils.e("请求数据失败，弹出失败信息");
                    showErrorTost(results.getRet(), results.getMsg());
                  //  onException(results.getRet());
                    return;
                }
                // 判断返回数据的类型 是对象 还是list
                JsonElement bodyBean = results.getBody();
                // 返回了一个对象。（但是存在一种情况是 对象和list同时存在，所以还得需要解析一下list）
                if (null != bodyBean) {
                    // bodyBean 存在 --将bodyBean转换成需要显示的对象
                    if (bodyBean.isJsonObject()) {
                        if (((JsonObject) bodyBean).size() > 0) {
                            LogUtils.e("是一个json对象,并且非空");
                            T pojo = JSONObject.parseObject(bodyBean.toString(), clazz);
                            doNext(pojo);
                        } else {
                            LogUtils.e("是一个json对象,但是是个空对象");
                            onEmpty();
                        }
                    }
                }
                // 判断是否有list数据  如果list==null 说明没有list标签 .
                // 由于该列表可能是分页数据   所以需要把totalCount返回给前端
                int totalCount = results.getTotalCount();
                JsonElement list = results.getList();
//                LogUtils.e("当前获取到的LIST :" + list);
                if (null == list) {
                    // 说明没有list标签 --不做处理 --
//                    LogUtils.e("没有list标签 --不做处理 --");
                } else {
//                    LogUtils.e("存在 list 标签");
                    // 存在list标签--则需要解析list 但是此时list可以为空 所以需要做个判断
                    if (list instanceof JsonPrimitive && "".equals(list.getAsString())) {
//                        LogUtils.e(" list 为空 onEmpty");
                        // 如果当前list为空，说明该次请求没有请求到列表数据 此时可以展示为onEmpty
                        onEmpty();
                    } else {
//                        LogUtils.e(" 此时list不为空 需要解析list数据 然后将list数据返回");
                        // 此时list不为空 需要解析list数据 然后将list数据返回
                        List<T> dataList = JSONArray.parseArray(list.toString(), clazz);
                        doNextList(totalCount, dataList);
                    }
                }
                // 如果既没有body对象 也没有 list对象 则把返回的数据直接传递到页面 自己处理
                boolean listIsEmpty = (null == results.getList());
                LogUtils.e("listIsEmpty :" + listIsEmpty);
                if (null == bodyBean && listIsEmpty && results.getTotalCount() == -1) {
                    doResult(results);
                }
                //判断数据是否需要缓存--
                if (!TextUtils.isEmpty(userKey)) {
                    SqlEntityBean entityBean = new SqlEntityBean();
                    entityBean.setKey(userKey);
                    if (null != bodyBean) {
                        entityBean.setValue(bodyBean.toString());
                    } else {
                        entityBean.setValue(results.getList().toString());
                    }
                    entityBean.setTime(System.currentTimeMillis());
                    DaoUtils.insertToDatabase(entityBean);
                }
            } else {
                // 没有获取到data数据--数据为空
                LogUtils.e("获取的数据为空啊");
                onEmpty();
            }
        } catch (Exception e) {
            e.printStackTrace();
            onError(e);
        }
    }

    /**
     * 服务器返回异常
     *
     * @param code
     */
    public void onException(int code) {
        //已经实现了onError方法
        LogUtils.e("服务器返错误 code" + code);
    }

    /**
     * 解析数据异常 或者是请求 异常
     * 一般是服务器错误 或者解析数据错误
     *
     * @param e
     */
    @Override
    public void onError(Throwable e) {
        //已经实现了onError方法
        LogUtils.e("解析数据异常-- ： " + e.getMessage());
    }

    /**
     * 该请求结束
     */
    @Override
    public void onComplete() {
    }

    /**
     * 显示接口错误提示
     * --该错误是自定义逻辑错误
     *
     * @param errorCode 错误码
     */
    public void showErrorTost(int errorCode, String msg) {
        ToastUtils.showShort(msg);
//        switch (errorCode) {
//            case ErrorCode.ERROR_CODE_A:
//                ToastUtils.showShort("ERROR_CODE_A");
//                break;
//            case ErrorCode.ERROR_CODE_B:
//                ToastUtils.showShort("ERROR_CODE_B");
//                break;
//            case ErrorCode.ERROR_CODE_207:
//                ToastUtils.showShort("ERROR_CODE_B");
//                break;
//            default:
//        }
    }

    /**
     * 如果既没有返回body 也没有返回list
     * 则把结果直接返回 交个页面自己单独处理
     *
     * @param response
     */
    public void doResult(Results response) {

    }

    /**
     * 接口请求数据 返回为空
     */
    public void onEmpty() {
        LogUtils.e("请求数据 BaseResult 解析为空 ");
    }

    /**
     * 返回T 对象
     * -一般用来获取详情数据
     *
     * @param t
     */
    public void doNext(T t) {
    }

    /**
     * 需要分页的列表数据
     *
     * @param totalCount
     * @param resultList
     */
    public void doNextList(int totalCount, List<T> resultList) {

    }

    public String getUserKey() {
        return userKey;
    }

    /**
     * 设置用户KEY  该KEY是用来缓存数据的
     *
     * @param userKey
     */
    public void setUserKey(String userKey) {
        this.userKey = userKey;
    }

    /**
     * 用户被踢出
     */
    public void loginOut() {

    }

}
